package com.easygoods.service;

import com.bestvike.stone.core.lang.RandomUtils;
import com.bestvike.stone.core.lang.StringUtils;
import com.bestvike.stone.spring.exception.BusinessException;
import com.bestvike.stone.spring.exception.ErrorCode;
import com.bestvike.stone.spring.service.BaseService;
import com.easygoods.dao.GoodsSkuDao;
import com.easygoods.dao.StockLockDao;
import com.easygoods.dao.StockRecordDao;
import com.easygoods.entity.GoodsSku;
import com.easygoods.entity.OrderGoods;
import com.easygoods.entity.StockLock;
import com.easygoods.entity.StockRecord;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

/**
 * Created by 许崇雷 on 2019-01-21.
 */
@Service
public class StockService extends BaseService {
    @Autowired
    private StockLockDao stockLockDao;
    @Autowired
    private GoodsSkuDao goodsSkuDao;
    @Autowired
    private StockRecordDao stockRecordDao;

    //获取可用库存
    public int getAvailableStock(String skuId) {
        Assert.hasText(skuId, "skuId can not be empty");
        return this.goodsSkuDao.getAvailableStock(skuId);
    }

    //锁定库存,注意按 skuId 顺序锁定
    @Transactional
    public String lockStock(GoodsSku goodsSku, int num, String reason, String orderId, String orderGoodsId) {
        if (goodsSku == null) {
            this.log.warn("goodsSku 为 null");
            throw new BusinessException(ErrorCode.ERROR_SERVER, "库存操作失败");
        }
        String skuId = goodsSku.getId();
        if (StringUtils.isEmpty(skuId)) {
            this.log.warn("skuId 为空");
            throw new BusinessException(ErrorCode.ERROR_SERVER, "库存操作失败");
        }
        if (num <= 0) {
            this.log.warn("num 为负数");
            throw new BusinessException(ErrorCode.ERROR_SERVER, "数量错误");
        }

        //插入表
        StockLock stockLock = new StockLock();
        stockLock.setId(RandomUtils.randomUUID());
        stockLock.setSkuId(skuId);
        stockLock.setNum(num);
        stockLock.setLockReason(reason);
        stockLock.setOrderId(orderId);
        stockLock.setOrderGoodsId(orderGoodsId);
        stockLock.beforeInsert();
        this.stockLockDao.insert(stockLock);
        //判断可用库存
        int availableStock = this.getAvailableStock(skuId);
        if (availableStock < 0) {
            this.log.warn("锁定库存时,库存不足 sku:" + skuId);
            throw new BusinessException(ErrorCode.ERROR_SERVER, "库存不足");
        }

        //插入日志
        StockRecord stockRecord = new StockRecord();
        stockRecord.setId(RandomUtils.randomUUID());
        stockRecord.setSkuId(skuId);
        stockRecord.setGoodsName(goodsSku.getSkuName());
        stockRecord.setSpuId(goodsSku.getSpuId());
        stockRecord.setNum(-num);
        stockRecord.setReason(reason);
        stockRecord.setOrderId(orderId);
        stockRecord.setOrderGoodsId(orderGoodsId);
        stockRecord.beforeInsert();
        this.stockRecordDao.insert(stockRecord);
        //返回锁主键
        return stockLock.getId();
    }

    //解锁库存
    @Transactional
    public void unlockStock(OrderGoods orderGoods, String reason) {
        //删除库存锁定表记录
        int stockLockNum = this.stockLockDao.deleteByPrimaryKey(orderGoods.getLockId());
        if (stockLockNum != 1) {
            throw new BusinessException(ErrorCode.ERROR_SERVER, "解锁库存锁定失败");
        }

        //插入库存锁定操作记录日志
        StockRecord stockRecord = new StockRecord();
        stockRecord.setId(RandomUtils.randomUUID());
        stockRecord.setSkuId(orderGoods.getSkuId());
        stockRecord.setGoodsName(orderGoods.getSkuName());
        stockRecord.setSpuId(orderGoods.getSpuId());
        stockRecord.setNum(orderGoods.getNum());
        stockRecord.setReason(reason);
        stockRecord.setOrderId(orderGoods.getOrderId());
        stockRecord.setOrderGoodsId(orderGoods.getId());
        stockRecord.beforeInsert();
        this.stockRecordDao.insert(stockRecord);
    }

    //扣减库存
    @Transactional
    public void outStock(OrderGoods orderGoods, String reason) {
        //扣减
        int count = this.goodsSkuDao.decreaseStock(orderGoods.getSkuId(), orderGoods.getNum());
        if (count != 1)
            throw new BusinessException(ErrorCode.ERROR_SERVER, "商品不存在");

        //解锁
        this.unlockStock(orderGoods, reason);
    }
}
